package logic

import (
	"context"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/promotion/model"
	"mall/service/promotion/rpc/internal/svc"
	"mall/service/promotion/rpc/internal/utils/errorhandler"
	"mall/service/promotion/rpc/types/promotion"

	"github.com/zeromicro/go-zero/core/logx"
)

type ScanPromotionActivityLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewScanPromotionActivityLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ScanPromotionActivityLogic {
	return &ScanPromotionActivityLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ScanPromotionActivityLogic) ScanPromotionActivity(in *promotion.ScanPromotionActivityReq) (*promotion.BaseResp, error) {
	err := l.scanPromotionActivity(in, globalkey.StatusNotStarted)
	if err != nil {
		return nil, err
	}

	err = l.scanPromotionActivity(in, globalkey.StatusStarted)
	if err != nil {
		return nil, err
	}

	return &promotion.BaseResp{}, nil
}

func (l *ScanPromotionActivityLogic) scanPromotionActivity(in *promotion.ScanPromotionActivityReq, status int32) error {
	var orderBys []string
	if len(in.OrderBy) > 0 {
		for _, orderBy := range in.OrderBy {
			var order string = " ASC"
			if orderBy.Order == "1" {
				order = " DESC"
			}

			switch orderBy.Field {
			case "id":
				orderBys = append(orderBys, model.PromotionActivityColumns.ID + order)
			}
		}
	}
	if len(orderBys) == 0 {
		orderBys = append(orderBys, model.PromotionActivityColumns.ID)
	}

	var stati string
	if len(in.FilterBy) > 0 {
		for _, filterBy := range in.FilterBy {
			if filterBy.Field == "status" {
				stati = strings.TrimSpace(filterBy.In)
			}
		}
	}

	var page uint64
	var pageSize uint64
	var restricted bool
	filterMap := make(map[string]map[string][]any)
	if in.Ids != nil {
		if vals := modelx.UniqueInterfaces(strings.TrimSpace(*in.Ids), 64); len(vals) > 0 {
			filterMap[model.PromotionActivityColumns.ID] = map[string][]any{
				"in": vals,
			}
			restricted = true
		}
	}
	if !restricted {
		page = in.Page
		pageSize = in.PageSize
	}

	statusIn := modelx.UniqueInterfaces(stati, 32)
	statusMap := make(map[string][]any)
	if len(statusIn) > 0 {
		statusMap["in"] = statusIn
	}
	if in.Status != nil && *in.Status > 0 {
		statusMap["equalTo"] = []any{*in.Status - 1}
	} else {
		statusMap["equalTo"] = []any{status}
	}
	filterMap[model.PromotionActivityColumns.Status] = statusMap

	now := time.Now()
	var newStatus int32
	if status == globalkey.StatusNotStarted {
		filterMap[model.PromotionActivityColumns.StartedAt] = map[string][]any{
			"lessThanOrEqualTo": []any{now.Add(time.Duration(-5 * time.Minute))},
		}
		newStatus = globalkey.StatusStarted
	} else if status == globalkey.StatusStarted {
		filterMap[model.PromotionActivityColumns.EndedAt] = map[string][]any{
			"lessThanOrEqualTo": []any{now.Add(time.Duration(-5 * time.Minute))},
		}
		newStatus = globalkey.StatusFinished
	}

	if newStatus == 0 {
		return nil
	}

	var orderBy string
	if len(orderBys) > 0 {
		orderBy = strings.Join(orderBys, ",")
	}
	list, _, err := l.svcCtx.Activity.GetList(l.ctx, model.M{
		"page":     page,
		"pageSize": pageSize,
		"orderBy":  orderBy,
	}, -1, filterMap)
	if err != nil {
		return errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	if len(list) == 0 {
		return nil
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	for _, data := range list {
		data.Status = uint16(newStatus)
		err = l.svcCtx.Activity.Update(l.ctx, tx, data, nil)
		if err != nil {
			tx.Rollback()
			return errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}
	}

	tx.Commit()

	return nil
}
